#include "dingdong.h"
#include <QFileDialog>
#include <QtGui/QMessageBox>
#include <QScrollArea>
#include <QColorDialog>
#include "ImageDownloader.h"
 #include <QBoxLayout>
#include "NewImageDialog.h"
#include "imageresizedialog.h"
#include "imagerotatedialog.h"
	static int imageID = 1;
DingDong::DingDong(QWidget *parent, Qt::WFlags flags)
	: QMainWindow(parent, flags)
{

	ui.setupUi(this);
	ui.PaintBrushOptions->hide();
	ui.EraserToolOptions->hide();

	//Setting up Click Events for toolbar buttons
	this->toolSignalMapper = new QSignalMapper(this);
	connect(toolSignalMapper, SIGNAL(mapped(QString)), this, SLOT(toggleTool(QString)));
	connect(ui.PaintBrush, SIGNAL(clicked()), toolSignalMapper, SLOT(map()));
	connect(ui.EraserTool, SIGNAL(clicked()), toolSignalMapper, SLOT(map()));
    connect(ui.EyedropperTool, SIGNAL(clicked()), toolSignalMapper, SLOT(map()));
	connect(ui.ZoomTool, SIGNAL(clicked()), toolSignalMapper, SLOT(map()));
	connect(ui.LineTool, SIGNAL(clicked()), toolSignalMapper, SLOT(map()));
	connect(ui.FillTool, SIGNAL(clicked()), toolSignalMapper, SLOT(map()));
	connect(ui.FunkyLineTool, SIGNAL(clicked()), toolSignalMapper, SLOT(map()));
    connect(ui.BasicShapeTool, SIGNAL(clicked()), toolSignalMapper, SLOT(map()));
	connect(ui.filterBrushTool, SIGNAL(clicked()), toolSignalMapper, SLOT(map()));
	connect(ui.TypeTool, SIGNAL(clicked()), toolSignalMapper, SLOT(map()));
	toolSignalMapper->setMapping(ui.PaintBrush, "PaintBrush");
	toolSignalMapper->setMapping(ui.EraserTool, "EraserTool");
    toolSignalMapper ->setMapping(ui.EyedropperTool, "EyedropperTool");
	toolSignalMapper->setMapping(ui.ZoomTool, "ZoomTool");
	toolSignalMapper->setMapping(ui.LineTool, "LineTool");
	toolSignalMapper->setMapping(ui.FunkyLineTool, "FunkyLineTool");
	toolSignalMapper->setMapping(ui.FillTool, "FillTool");
	toolSignalMapper->setMapping(ui.BasicShapeTool, "BasicShapeTool");
	toolSignalMapper->setMapping(ui.filterBrushTool, "filterBrushTool");
	toolSignalMapper->setMapping(ui.TypeTool, "TypeTool");

	//Connecting the Filters up to the Filter Signal Mapper...
	//Should look into a new way to handle this...it definetley
	//needs to be moved to its own area.
	this->filterSignalMapper = new QSignalMapper(this);
	connect(filterSignalMapper, SIGNAL(mapped(QString)), this, SLOT(applyFilter(QString)));

	connect(ui.actionInvert, SIGNAL(triggered()), filterSignalMapper, SLOT(map()));
	filterSignalMapper->setMapping(ui.actionInvert, "negative");
	connect(ui.actionDesaturate, SIGNAL(triggered()), filterSignalMapper, SLOT(map()));
	filterSignalMapper->setMapping(ui.actionDesaturate, "grayscale");

	connect(ui.actionPixelate, SIGNAL(triggered()), filterSignalMapper, SLOT(map()));
	filterSignalMapper->setMapping(ui.actionPixelate, "pixelation");
	connect(ui.actionSepia, SIGNAL(triggered()), filterSignalMapper, SLOT(map()));
	filterSignalMapper->setMapping(ui.actionSepia, "sepia");
	connect(ui.actionBlur, SIGNAL(triggered()), filterSignalMapper, SLOT(map()));
	filterSignalMapper->setMapping(ui.actionBlur, "gaussian");
	connect(ui.actionFind_Edges, SIGNAL(triggered()), filterSignalMapper, SLOT(map()));
	filterSignalMapper->setMapping(ui.actionFind_Edges, "edgeDetect");
	connect(ui.actionEmboss, SIGNAL(triggered()), filterSignalMapper, SLOT(map()));
	filterSignalMapper->setMapping(ui.actionEmboss, "emboss");
	connect(ui.actionSharpen, SIGNAL(triggered()), filterSignalMapper, SLOT(map()));
	filterSignalMapper->setMapping(ui.actionSharpen, "sharpen");


	currentTool = new QLabel(this);
	currentTool->blockSignals(true);
	currentTool->setMaximumSize(0,0);
	currentTool->setText("");
	currentTool->setObjectName("currenTool");

	this->setObjectName("MainWindow");
	imageTabs = new QTabWidget(this);
	setCentralWidget(imageTabs);
	connect(ui.actionNew, SIGNAL(triggered()), this, SLOT(newImage()));
    connect(ui.actionOpen, SIGNAL(triggered()), this, SLOT(open()));
	connect(ui.actionExit, SIGNAL(triggered()), this, SLOT(exit()));
	connect(ui.actionClose, SIGNAL(triggered()), this, SLOT(close()));
	connect(ui.actionSave, SIGNAL(triggered()), this, SLOT(save()));
	connect(ui.actionSave_As, SIGNAL(triggered()), this, SLOT(saveAs()));
	connect(ui.actionColor, SIGNAL(triggered()), this, SLOT(colorPicker()));
	connect(ui.actionZoom_In, SIGNAL(triggered()), this, SLOT(zoomIn()));
    connect(ui.actionZoom_Out, SIGNAL(triggered()), this, SLOT(zoomOut()));
	connect(ui.actionUndo, SIGNAL(triggered()), this, SLOT(undo()));
	connect(ui.actionRedo, SIGNAL(triggered()), this, SLOT(redo()));

	connect(ui.actionImage_Size, SIGNAL(triggered()), this, SLOT(resizeImage()));

	connect(ui.actionOpenUrl, SIGNAL(triggered()), this, SLOT(downloadImage()));
	connect(ui.actionImage_Size, SIGNAL(triggered()), this, SLOT(resizeImage()));

	connect(ui.actionRotate, SIGNAL(triggered()), this, SLOT(rotateImage()));
	connect(ui.actionRotate_90_CW, SIGNAL(triggered()), this, SLOT(rotateImageClockwise()));


	connect(ui.brushSizeSlider, SIGNAL(sliderReleased()), this, SLOT(resizeBrush()));
	connect(ui.eraserSizeSlider, SIGNAL(sliderReleased()), this, SLOT(resizeEraser()));

   

}

void DingDong::rotateImageClockwise()
{
	PaintArea* ourImage = getCurrentImage();
	QImage* imageToRotate = ourImage->getImage();
	QTransform rotation;
	rotation.rotate(90);
	ourImage->setImage(imageToRotate->transformed(rotation, Qt::SmoothTransformation));
	ourImage->resize(imageToRotate->width(), imageToRotate->height());
	ourImage->update();
	imageTabs->currentWidget()->repaint();
}


void DingDong::rotateImage()
{
	ImageRotateDialog* imageRotateDiag = new ImageRotateDialog();
	imageRotateDiag->exec();
	PaintArea* ourImage = getCurrentImage();
	QImage* imageToRotate = ourImage->getImage();
	QTransform rotation;
	rotation.rotate(90);
	ourImage->setImage(imageToRotate->transformed(rotation, Qt::SmoothTransformation));
	ourImage->resize(imageToRotate->width(), imageToRotate->height());
	ourImage->update();
	imageTabs->currentWidget()->repaint();
}

void DingDong::newImage()
{

	NewImageDialog* newImgDiag = new NewImageDialog();
	newImgDiag->exec();

	ImageScrollArea *newImageScrollArea = new ImageScrollArea;
	QString name = "new_image1"+char(imageID);
	PaintArea *newImage = new PaintArea();
	newImage->resizeImage(*newImgDiag->getNewSize());
	newImage->setObjectName(name);
	addNewImageTab(newImage);
	++imageID;
}




void DingDong::addNewImageTab(PaintArea *newImage)
{
	ImageScrollArea *newImageScrollArea = new ImageScrollArea;
	newImageScrollArea->setObjectName(newImage->objectName());
	newImageScrollArea->addPaintArea(newImage);
	imageTabs->addTab(newImageScrollArea, newImage->objectName());
	if (newImage->getImage()->height() > this->height() ||
		newImage->getImage()->width() > this->width())
 		this->resize(newImage->getImage()->width()+500, newImage->getImage()->height());
	
	imageTabs->setCurrentWidget(newImageScrollArea);
}

void DingDong::close()
{
	imageTabs->currentWidget()->deleteLater();
	
	PaintArea *currentPaintArea = getCurrentImage();
	delete currentPaintArea;
	imageTabs->removeTab(imageTabs->currentIndex());
}

void DingDong::save()
{

	QString fileLocation = imageTabs->tabText(imageTabs->currentIndex());
    PaintArea *currentImage = imageTabs->findChild<PaintArea*>(fileLocation);
	currentImage->saveImage(fileLocation, QFileInfo(fileLocation).completeSuffix().toStdString().c_str());
}

void DingDong::saveAs()
{
	QFileDialog *fileDailog = new QFileDialog(this);
	QString fileName =  fileDailog->getSaveFileName(this, tr("Save as....."), "",
    tr("JPG (*.jpg );;.PNG(*.png)"));
	
	QFile file(fileName);

	QFileInfo *fileInfo = new QFileInfo(file);

	PaintArea *currentImage = imageTabs->findChild<PaintArea*>();


	currentImage->saveImage(fileName, fileInfo->suffix().toStdString().c_str());
}


void DingDong::open()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",
        tr("Image Files (*.jpg *.png)"));

    if (fileName != "") {
        QFile file(fileName);
        if (!file.open(QIODevice::ReadOnly)) {
            QMessageBox::critical(this, tr("Error"), tr("Could not open file"));
            return;
        }
		QFileInfo *fileInfo;

		try
		{
			fileInfo= new QFileInfo(file);
		}

		catch(...) 
		{
			/*TO-DO: Add Error Handling*/
			std::string errors = "Error loading file";
		}
		PaintArea *newImage = new PaintArea();
		newImage->openImage(fileInfo->absoluteFilePath());
		addNewImageTab(newImage);

        file.close();
    }


}






void DingDong::resizeBrush()
{
	imageTabs->update();
	PaintBrush::setBrushSize(ui.brushSizeSlider->value());
}

void DingDong::resizeEraser()
{
	imageTabs->update();
	EraserTool::setEraserSize(ui.eraserSizeSlider->value());
}

void DingDong::downloadImage()
{
	ImageDownloader* imgDl = new ImageDownloader();


	imgDl->downloadBegin();

	QEventLoop loop;
	QObject::connect(imgDl->netReply, SIGNAL(finished()), &loop, SLOT(quit()));
	loop.exec();

	imgDl->downloadFinished();
	QString newName = "yup";
	PaintArea *newImage = new PaintArea(this);
	newImage->setObjectName(newName);
	//newImage->openImage(imgDl->urlImage);

	imageTabs->addTab(newImage, "newImage" + newName);
	imageTabs->setCurrentWidget(newImage);



}
PaintArea* DingDong::getCurrentImage()
{
	QString fileLocation = imageTabs->tabText(imageTabs->currentIndex());
	PaintArea *currentImage = imageTabs->currentWidget()->findChild<PaintArea*>(fileLocation);
	return currentImage;
}
void DingDong::undo()
{
	PaintArea* currentImage = getCurrentImage();
	currentImage->undo();
	currentImage->update();
}

void DingDong::redo()
{
	PaintArea* currentImage = getCurrentImage();
	currentImage->redo();
	currentImage->update();


}

DingDong::~DingDong()
{

}


void DingDong::applyFilter(const QString &filterName)
{
	Filter* ourLovelyFilter = filterFactory.createFilter(filterName.toStdString());
	if(getCurrentImage()->getUndoPointer() == -1)
		getCurrentImage()->saveUndoState();

	ourLovelyFilter->apply(getCurrentImage()->getImage());
	getCurrentImage()->update();
	getCurrentImage()->saveUndoState();
}



//When setting the text of the current tool, set it to be equal
//to the widget name given to the tool in ui_dingdong.h

void DingDong::toggleTool(const QString toolName)
{
		//Refactored by aDavis - 03/05/2012

		if(this ->currentTool->text() != "" )
		{
			QToolButton* selectedTool = this->findChild<QToolButton*>(this ->currentTool->text());
			selectedTool ->setChecked(false);              
		}
		if (toolName != this ->currentTool->text()){

			QToolButton* aselectedTool = this->findChild<QToolButton*>(toolName);
			aselectedTool->setChecked(true);
			this->currentTool->setText(toolName);
		}

		ui.ToolOptions->setWidget(this->findChild<QWidget*>(toolName+"Options"));


}




void DingDong::exit()
{
	qApp->quit();

}


void DingDong::zoomIn()
{
	scale(1.6);
		
}

void DingDong::zoomOut()
{
	scale(.625);	
}

//Refacoted on 03/24 - May be able to be placed in outside class
//AD
void DingDong::resizeImage()
{
	PaintArea* ourImage = getCurrentImage();

	if(ourImage->getUndoPointer() == -1)
		ourImage->saveUndoState();

	QImage originalImage = *ourImage->getImage();
	ImageResizeDialog* imgSizeDiag = new ImageResizeDialog(this, originalImage.width(), originalImage.height());

	imgSizeDiag->exec();
	
	QSize* newSize = imgSizeDiag->getNewSize();

	QImage newImage = originalImage.scaled(newSize->width(), newSize->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
	ourImage->resize(newSize->width(), newSize->height());
	ourImage->setImage(newImage);
	ourImage->saveUndoState();
	ourImage->update();
	
	


}
void DingDong::scale(double factor)
{
	QLabel *imgLabel = imageTabs->currentWidget()->findChild<QLabel *>(); 
	const QPixmap *currentPixmap = imgLabel->pixmap();          
	QImage currentImage = currentPixmap->toImage(); 
	
	imgLabel -> resize(factor * imgLabel -> size());
}


void DingDong::colorPicker()
{
	PaintArea *currentImage = imageTabs->findChild<PaintArea*>();
	QColorDialog *color = new QColorDialog;
	QColor selectedColor = QColorDialog::getColor(Qt::red, this, "Text Color",  QColorDialog::DontUseNativeDialog);
	PaintBrush::brushColor = selectedColor;
}


